#include "util.h"
#include "log.h"
#include "conf.h"
#include "version.h"

static void terminate(int sig, short what, void* ctx)
{
	event_base_loopbreak((struct event_base*)ctx);
}

static void usage(const char* prog)
{
	printf(
		"Usage: %s [-hvt] [-c config]\n"
		"  -h           help(this message)\n"
		"  -v           print version\n"
		"  -t           test config file syntax\n",
		prog);
}

static int read_config_file(const char* config_file)
{
	int err;

	log_init(NULL, false, true, true);
	err = config_init(config_file);
	if (err)
	{
		log_error("read configuration from %s failed.", config_file);
		config_fini();
	}

	log_fini();
	return err;	
}

int generic_main(bool server, int argc, char** argv, evconnlistener_cb accept_cb, void* accept_cb_args, evconnlistener_errorcb error_cb)
{
	struct event_base* evbase = NULL;
	struct evconnlistener* listener = NULL;
	struct event* sig_term = NULL;
	struct event* sig_int = NULL;
	struct blue_config* config;

	const char* config_file = "bluesocket.conf";
	bool config_test = false;
	int opt;
	int err;

	while ((opt = getopt(argc, argv, "hvtc:")) != -1)
	{
		switch (opt) 
		{
		case 't':
			config_test = true;
			break;
		case 'c':
			config_file = optarg;
			break;
		case 'h':
			usage(argv[0]);
			return EXIT_SUCCESS;
		case 'v':
			puts(VERSION);
			return EXIT_SUCCESS;
		default:
			usage(argv[0]);
			return EXIT_FAILURE;
		}
	}

	err = read_config_file(config_file);
	if (err)
		return EXIT_FAILURE;

	if (config_test)
		return EXIT_SUCCESS;

	config = get_config();

	log_init(config->log_file, config->debug_log, config->info_log, config->error_log);
	socket_init();

	do
	{
		evbase = event_base_new();
		sig_term = event_new(evbase, SIGTERM, EV_SIGNAL|EV_PERSIST, terminate, evbase);
		sig_int = event_new(evbase, SIGINT,   EV_SIGNAL|EV_PERSIST, terminate, evbase);
		event_add(sig_term, NULL);
		event_add(sig_int, NULL);

		if (server)
			listener = tcp_listen(config->server_addr, config->server_port, evbase, accept_cb, accept_cb_args, error_cb);
		else
			listener = tcp_listen(config->local_addr, config->local_port, evbase, accept_cb, accept_cb_args, error_cb);

		if (!listener)
			break;

		event_base_dispatch(evbase);
	} while (0);


	if (listener)
		evconnlistener_free(listener);

	if (sig_term)
	{
		event_del(sig_term);
		event_free(sig_term);
	}

	if (sig_int)
	{
		event_del(sig_int);
		event_free(sig_int);
	}

	if (evbase)
		event_base_free(evbase);

	config_fini();
	socket_fini();
	log_fini();
	return 0;
}


